// -------------------------------------------------------------------------------------
// FileUtils.m - file manipulation utilities
// Martin D. Flynn, NeXT Computer, Inc.
// You may freely copy, distribute and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to its
// fitness for any particular use.
// -------------------------------------------------------------------------------------

#import <stdlib.h>
#import <string.h>
#import <libc.h>
#import <sys/dir.h> 			// for getdirentries()
#import <objc/objc-class.h>		// for class_getInstanceMethod()
#import <objc/hashtable.h>		// for NXCopyStringBuffer()
#import "FileUtils.h"

// -------------------------------------------------------------------------------------
// return the number of arguments taken by the specified method
@implementation Object(methodNumberOfArgs)
static int _methodNumberOfArgs(Object *obj, SEL aSelector)
{
	Method	m = class_getInstanceMethod(obj->isa, aSelector);
	if (!m) m = class_getClassMethod(obj->isa, aSelector);
	return (m)? method_getNumberOfArguments(m) - 2: -1;
}
@end

// -------------------------------------------------------------------------------------
@implementation FileUtils : Object

// -------------------------------------------------------------------------------------
// file directory from fully qualified path/file
// -------------------------------------------------------------------------------------

/* send all files found in a specified directory to the specified action method */
+ sendFileDirectory:(const char*)dirPath toTarget:target method:(SEL)method with:anArg
{
	long          basep;
	char          *buf;
	struct direct *dp;
	int           argc, cc, fd;
	char          dirbuf[8192];
	char          fullPath[MAXPATHLEN];
  
	/* open file path */
	fd = open(dirPath, O_RDONLY, 0644);
	if (fd <= 0)return (id)nil;

	/* get number of accepted args */
	argc = _methodNumberOfArgs(target, method);
  
	/* open file path */
	cc = getdirentries(fd, (buf = dirbuf), sizeof(dirbuf), &basep);
	while (cc) {
		dp = (struct direct *)buf;
		if (*(dp->d_name) && strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
			sprintf(fullPath, "%s/%s", dirPath, dp->d_name);
			if (argc == 1) [target perform:method with:(void*)fullPath];
			else [target perform:method with:(void*)fullPath with:anArg];
		}
		buf += dp->d_reclen;
		if (buf >= dirbuf + cc)
			cc = getdirentries(fd, (buf = dirbuf), sizeof(dirbuf), &basep);
    }

	/* close path and return list */
	close(fd);
	return self;
  
}

// -------------------------------------------------------------------------------------
// extract file name from fully qualified path/file
// -------------------------------------------------------------------------------------

/* extract 'name.ext' from fully qualified file name */
+ (const char*)extractFileNameExt:(const char*)fileName
{
	char	*temp;
	return (temp=rindex(fileName, '/'))? temp + 1 : fileName;
}

/* extract '.ext' from fully qualified file name */
+ (const char*)extractFileExt:(const char*)fileName
{
	char		*temp;
	static char	*nullStr = "";
	return (temp=rindex(fileName, '.'))? temp : nullStr;
}

/* extract and copy file from fully qualified file name */
+ (char*)copyFileName:(const char*)fileName
{
	char	name[MAXPATHLEN], *temp;
	strcpy(name, fileNAMEXT(fileName));
	if (temp=rindex(name, '.')) *temp = 0;
	return NXCopyStringBuffer(name);
}

/* extract and copy file from fully qualified file name */
+ (char*)copyFilePath:(const char*)fileName
{
	int		len;
	char	*temp, *path;
	if (!(temp=rindex(fileName, '/'))) return (char*)nil;
	len = temp - fileName;
	path = (char*)malloc(len + 1);
	strncpy(path, fileName, len);
	path[len] = 0;
	return path;
}

@end
